Migrating from Log4j 1
Log4j 1 has reached End of Life in 2015, and is no longer supported. Vulnerabilities reported after August 2015 against Log4j 1 are not checked and will not be fixed. Users should upgrade to Log4j 2 to obtain security fixes. |
Since Log4j 2 has been rewritten from scratch, it introduces many breaking changes to its predecessor. Most notably:
-
It uses a new package namespace (
org.apache.logging.log4j
), whereas Log4j 1 used theorg.apache.log4j
namespace, -
It features a logging API which is independent of its reference implementation,
-
It uses a new more flexible configuration file format, which is incompatible with the format used by Log4j 1.
Prepare to migrate
Are you a library developer?
If you are developing a library, which functionality is not related to logging, you only need to rewrite the library to use Log4j 2 API. Skip directly to Log4j 1 API migration. |
In order to migrate your application to Log4j 2 you need to assess first how your application and its dependencies use Log4j 1. While Log4j 1 didn’t have a formal split between a logging API and a logging backend, for the purpose of this guide, we’ll introduce the following split:
- Log4j 1 API
-
It is the part of the Log4j 1 library that produces log events, and it is the most commonly used. The methods that are considered part of the Log4j 1 API are listed below:
Table 1. Log4j 1 API methods Class name Methods All methods
All methods
All methods
All methods
All methods, except: methods for the AppenderAttachable interface,
callsAppenders
andsetLevel
.Same as
Category
All methods
- Log4j 1 Backend
-
This is the part of the logging library that consumes log events, formats them and writes to their destination. It also allows to configure Log4j 1 programmatically. It is usually not used in code, since the recommended way to configure Log4j 1 is through a configuration file.
While it is fairly simple to check which classes and methods in the All the libraries that use Log4j 1 API in their code must have a compile dependency on either log4j:log4j or its clone ch.qos.reload4j:reload4j. There are however misconfigured libraries that declare those dependencies, even if they don’t directly use Log4j 1 at all. To distinguish between libraries that use Log4j 1 and those that don’t, you can look for the presence of other logging APIs. If a library directly depends on:
it is fair to assume that it uses those libraries instead of Log4j 1 API, even if it has a direct dependency on |
The following sections explain how to migrate from Log4j 1 to Log4j 2, depending on the way Log4j 1 is used in your application:
-
if your application or one of its dependencies is coded against Log4j 1 API, see Log4j 1 API migration,
-
if your application uses Log4j 1 only as logging backend, see Log4j 1 Backend migration.
Log4j 1 API migration
To migrate an application that uses Log4j 1 API as logging API, the recommended approach is to modify your code. See Migrate code from Log4j 1 API to Log4j 2 API for details.
In the case one of your libraries uses Log4j 1 API or you can not modify your logging code at the moment, a Log4j 1 to Log4j 2 bridge is available. See Use Log4j 1 to Log4j 2 API bridge for details.
Migrate code from Log4j 1 API to Log4j 2 API
You can migrate your code from Log4j 1 to Log4j 2 automatically, by using the Log4j1ToLog4j2 OpenRewrite recipe. See OpenRewrite site for more details. |
Except the change in the package name from org.apache.log4j
to org.apache.logging.log4j
, most of the class and method names in Log4j 2 API are inherited from Log4j 1 API.
In order to migrate you code, you need to:
-
modify the imports and types used by your application, according to the following table:
Table 2. Migration of types from Log4j 1 to Log4j 2 Migrate Log4j 1 type to Log4j type -
Some Log4j 1 methods were renamed or moved to a different class. Therefore, you need to replace the following methods with their Log4j 2 API equivalents:
Table 3. Migration of methods from Log4j 1 to Log4j 2 Migrate Log4j 1 method to Log4j method -
Finally, some methods need specific conversion rules to be applied:
Table 4. Special Log4j 1 method migration rules Method Description Remove the
LoggerFactory
parameter and use one of Log4j 2’s other extension mechanisms.Since Log4j 2.6, an equivalent
o.a.l.l.LogManager.shutdown()
method can be used.The utility of this method call depends upon the logging backend used with Log4j API.
The Log4j Core backend automatically adds a JVM shutdown hook on start up to perform any cleanups, so the
LogManager.shutdown()
call can be safely removed. Starting in Log4j 2.1, you can also specify a custom ShutdownCallbackRegistry.See log4j2.shutdownCallbackRegistry for more details.
Non Log4j 1 API methods
Methods outside of those listed in [log4j-1-api-methods], such as
Logger.setLevel()
need to be replaced with a method call specific to the logging backend used by the application.Some third-party integrators, such as Spring Boot, provide utility methods that let you abstract the logging backend, e.g. the
LoggingSystem.setLogLevel()
Spring Boot method.
To prevent a performance penalty from string concatenation in disabled log statements, Log4j 1 required the use of
Since Log4j 2 API introduces parameterized logging these guards are no longer necessary and the same statement can be rewritten as:
|
Use Log4j 1 to Log4j 2 API bridge
If you can not modify your application’s code or one of your dependencies is using Log4j 1 API as logging API, you can delay the migration process by installing the Log4j 1 to Log4j 2 bridge.
Since forwarding Log4j 1 API calls to Log4j 2 API calls is the basic functionality of the bridge, no further configuration is required from your part.
Log4j 1 Backend migration
If your application uses Log4j 1 only as logging backend bound to another logging API, such as Apache Commons Logging (JCL) or SLF4J, you only need to:
-
Configure all logging bridges to log to Log4j 2 API instead. This can be done by replacing the following dependencies on your application’s runtime classpath:
Table 5. Dependency migration from Log4j 1 to Log4j 2 Replace Log4j 1 dependency with Log4j 2 dependency either upgrade to version 1.3.0 (or later)
or replace with
org.apache.logging.log4j:log4j-jcl
See Installation for more details.
-
Convert your configuration files from the Log4j 1 to the Log4j 2 configuration format. See Log4j 1 Configuration file migration below for more details.
Migrate Log4j 1 custom components
Since Log4j 1 offered a limited amount of appenders and layouts, over the years users implemented many custom components that offered additional features. If you are currently using a custom Log4j 1 component you should proceed as follows:
-
Log4j 2 provides many improvements to Log4j 1 components and many new components. Check if the feature offered by your custom component is not already available in Log4j 2. If you can not find the feature, ask on our support channels.
-
Since Log4j 2.17.2, the Log4j 1 to Log4j 2 bridge has a limited support for using native Log4j 1 appenders and layouts. Native Log4j 1 components can only be configured using Log4j 1 configuration files (see Use Log4j 1 to Log4j 2 bridge) and require the installation of the Log4j 1 to Log4j 2 bridge.
Mixing Log4j 1 and Log4j 2 components will most certainly reduce the performance of the logging system.
-
If your Log4j 1 native component is not supported by the Log4j 1 to Log4j 2 bridge, we suggest to rewrite it directly as Log4j 2 component. See Extending for more details.
Log4j 1 Configuration file migration
Convert configuration file from Log4j 1 to Log4j 2
Although the Log4j 2 configuration syntax is different from that of Log4j 1, most, if not all, of the same functionality is available.
The
|
Interpolation
Log4j 1 only supports interpolation using system properties and properties from the log4j.properties
file using the ${foo}
syntax.
Log4j 2 extended this mechanism, by introducing pluggable Lookups.
In order to convert a Log4j 1 configuration file that uses interpolation to a Log4j 2 configuration file, replace all occurrences of ${foo}
with ${sys:foo}
.
Appenders
Log4j 2 contains an equivalent for most Log4j 1 appenders:
Log4j 1 appender | Log4j 2 equivalent | Notes |
---|---|---|
Does not support custom layouts. |
||
The rolling file appender in Log4j 2 is based on the org.apache.log4j.rolling.RollingFileAppender from Apache™ Extras for Apache Log4j® and additional care must be taken to convert the Log4j 1 rolling appenders to their Log4j 2 equivalent:
-
Log4j 2 by default uses a different strategy to determine the index of the archived log files. Log4j 1 always rolls the current log file (e.g.
app.log
) to a log file with index1
(e.g.app.log.1
). Log4j 2 on the other hand uses the first available index (e.g.app.log.42
if filesapp.log.1
thruapp.log.41
already exist).To use the same algorithm to determine the index of the logged file in Log4j 1 and Log4j 2, you need to configure the
fileIndex
attribute of the default rollover strategy tomin
.<DefaultRolloverStrategy fileIndex="min"/>
-
The two rolling file appenders available in Log4j 1, use an implicit file pattern and triggering policy for the archived log files. If the current log file is called
app.log
, you need to configure the Log4j 2 rolling file appender with the followingfilePattern
and triggering policy configuration options:
Log4j 1 appender | Log4j 2 filePattern |
Log4j 2 triggering policy |
---|---|---|
|
|
|
|
|
Layouts
Log4j 1 layouts can be converted to Log4j 2 layouts using the following conversion rules:
- org.apache.log4j.EnhancedPatternLayout
-
can be converted to a
PatternLayout
that uses the same pattern, - org.apache.log4j.HTMLLayout
-
can be converted to an
HtmlLayout
. - org.apache.log4j.PatternLayout
-
can be converted to a
PatternLayout
that uses the same pattern, - org.apache.log4j.SimpleLayout
-
can be converted to a
PatternLayout
that uses the%p - %m%n
pattern, - org.apache.log4j.TTCCLayout
-
can be converted to a
PatternLayout
that uses the%r [%t] %p %c %notEmpty{%x }- %m%n
pattern, - org.apache.log4j.xml.XMLLayout
-
does not have an exact equivalent in Log4j 2 Core. If backward compatibility is required, you can install the Log4j 1 to Log4j 2 bridge and use the
Log4j1XmlLayout
plugin.
The formatting of the
|
Use Log4j 1 to Log4j 2 bridge
If you cannot convert your configuration files from Log4j 1 to Log4j 2, the Log4j 1 to Log4j 2 bridge can convert your configuration files at runtime. To use this feature, you need to Install the Log4j 1 to Log4j 2 bridge and set one of the following configuration properties:
log4j1.compatibility
Env. variable |
LOG4J_COMPATIBILITY |
---|---|
Type |
|
Default value |
|
If set to true
, Log4j 2 will:
-
Scan the classpath to find Log4j 1 configuration files in the following standard locations:
-
log4j-test.properties
, -
log4j-test.xml
, -
log4j.properties
, -
log4j.xml
.
-
-
(since
2.24.0
) Enable the usage of theo.a.log4j.PropertyConfigurator
ando.a.log4j.xml.DOMConfigurator
classes in your code.
log4j.configuration
Env. variable |
LOG4J_CONFIGURATION_FILE |
---|---|
Type |
|
Default value |
|
If not null
, Log4j 2 will try to retrieve a Log4j 1 configuration file from the given location.
The configuration file name must end in .properties
(Log4j 1 properties format) or .xml
(Log4j 1 XML format).
See also
limitations of Log4j 1 configuration compatibility layer.
Limitations of runtime configuration conversion
The support for Log4j 1 configuration files uses Log4j 2 Core plugin system and can be extended by implementing a plugin of type
org.apache.log4j.builders.Builder
.
The Log4j 1 to Log4j 2 bridge supports out-of-the-box the following Log4j 1 and Apache Extras for Log4j 1 components:
- Appenders
-
- Filters
- Layouts
-
-
org.apache.log4j.PatternLayout
andorg.apache.log4j.EnhancedPatternLayout
,
- Triggering policies
See the plugin reference for a complete list.
Log4j 1 to Log4j 2 bridge
To help users with the migration process, a Log4j 1 to Log4j 2 bridge is available. The bridge can fulfill four separate functions:
-
It forwards all Log4j 1 API method calls to the Log4j 2 API. See how to use the bridge for Log4j 1 API migration for more details.
-
Since version 2.17.2 the bridge supports the usage of some components written for Log4j 1 inside Log4j 2 Core. See how to use the bridge for Log4j 1 Backend migration for more details.
-
It provides limited support for programmatic configuration of Log4j 2 Core, using Log4j 1 method calls. This functionality requires the
log4j1.compatibility
configuration property to be set totrue
. -
It provides a limited support for Log4j 1 configuration file formats. See how to use the bridge for Log4j 1 Configuration file migration for more details.
Installation
Since the Log4j 1 to Log4j 2 Bridge replaces Log4j 1 classes, it is incompatible with the following artifacts:
Before installing the bridge, you need to make sure that none of the artifacts above are present in your runtime classpath.
To install the bridge, add the following dependency to your application:
-
Maven
-
Gradle
We assume you use log4j-bom
for dependency management.
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-1.2-api</artifactId>
<scope>runtime</scope>
</dependency>
We assume you use log4j-bom
for dependency management.
runtimeOnly 'org.apache.logging.log4j:log4j-1.2-api'
When to stop using the Log4j 1 to Log4j 2 bridge
The Log4j 1 to Log4j 2 bridge is not conceived as a long term solution. Once:
-
you have migrated your logging code to use Log4j 2 API (see Migrate code from Log4j 1 API to Log4j 2 API),
-
you have migrated your configuration files to use the Log4j 2 configuration format (see Log4j 1 Configuration file migration),
-
upgraded all the dependencies that use Log4j 1 directly to newer versions that use a proper logging API (JCL, Log4j 2 API, JBoss logging, SLF4J),
the bridge is no longer necessary and should be removed.
The separation of logging APIs from logging implementations started in 2002, with the release of Apache Commons Logging (formerly known as Jakarta Commons Logging). We are unaware of any maintained library that is currently using Log4j 1. However, if this is your case, please contact the library maintainer and ask them to migrate to one of the available logging APIs. |